mod args;
mod server;
mod table;

#[macro_use]
extern crate log;

use std::{cell::Cell, error::Error, process::ExitCode, sync::LazyLock};

use args::{CliArguments, Command};
use clap::Parser;

/// The CLI arguments.
static ARGS: LazyLock<CliArguments> = LazyLock::new(CliArguments::parse);

thread_local! {
    /// The exit code of the program.
    static EXIT: Cell<ExitCode> = const { Cell::new(ExitCode::SUCCESS) };
}

/// The entry point of the program.
fn main() -> ExitCode {
    let res = dispatch();

    if let Err(err) = res {
        error!("{}", err);
        set_failed();
    }

    EXIT.with(|exit| exit.get())
}

/// Dispatches the command.
fn dispatch() -> Result<(), Box<dyn Error>> {
    match &ARGS.command {
        Command::Table(command) => table::dispatch(command),
        Command::Server(command) => server::dispatch(command),
    }
}

/// Sets the exit code to failure.
fn set_failed() {
    EXIT.with(|exit| exit.set(ExitCode::FAILURE));
}
